@page "/tree-grid/dynamic-object"

@using Syncfusion.Blazor.TreeGrid
@using Syncfusion.Blazor.Grids
@using System.Dynamic;
@*Hidden:Lines*@
@using BlazorDemos
@inherits SampleBaseComponent;
@*End:Hidden*@
<SampleDescription>
    <p>This sample explains about the usage of DynamicObject data binding with CRUD operations, sorting, filtering, and aggregate functionalities in the Tree Grid component with DynamicObject.</p>
</SampleDescription>
<ActionDescription>
    <p>DynamicObject can be bound to Tree Grid by assigning to the <code><a target='_blank' class='code' href='https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.TreeGrid.SfTreeGrid-1.html#Syncfusion_Blazor_TreeGrid_SfTreeGrid_1_DataSource'>DataSource</a></code> property.</p>
    <p>The <code><a target='_blank' class='code' href='https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.dynamicobject.getdynamicmembernames?view=netcore-3.1'> GetDynamicMemberNames</a></code> method of the DynamicObject class must be overridden and return the property names to render and perform data operations, editing etc., while using DynamicObject.</p>
    <p>More information on the DynamicObject data binding can be found in this <a target='_blank' href='https://blazor.syncfusion.com/documentation/treegrid/data-binding/#dynamicobject-binding'>documentation section</a>.</p>
</ActionDescription>

<div class="col-lg-12 control-section">
    <div class="content-wrapper">
        <div class="row">
            <SfTreeGrid DataSource="@TreeData" @ref="TreeGrid" AllowPaging="true" AllowFiltering="true" AllowSorting="true" Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })" IdMapping="TaskID" ParentIdMapping="ParentID" TreeColumnIndex="1">
                <TreeGridEditSettings AllowEditing="true" AllowAdding="true" AllowDeleting="true" NewRowPosition="RowPosition.Below" />
                <TreeGridPageSettings PageSize="2" PageSizeMode="PageSizeMode.Root"></TreeGridPageSettings>
                <TreeGridAggregates>
                    <TreeGridAggregate>
                        <TreeGridAggregateColumns>
                            <TreeGridAggregateColumn Field="Duration" Type="Syncfusion.Blazor.Grids.AggregateType.Sum" Format="C2">
                                <FooterTemplate>
                                    @{
                                        var SumValue = (context as Syncfusion.Blazor.Grids.AggregateTemplateContext);
                                        <div>
                                            <p>Sum: @SumValue.Sum</p>
                                        </div>
                                    }
                                </FooterTemplate>
                            </TreeGridAggregateColumn>
                        </TreeGridAggregateColumns>
                    </TreeGridAggregate>
                </TreeGridAggregates>
                <TreeGridColumns>
                    <TreeGridColumn Field="TaskID" HeaderText="Task ID" Width="100" IsPrimaryKey="true" ValidationRules="@(new ValidationRules{ Required=true, Number=true})" TextAlign="TextAlign.Right"></TreeGridColumn>
                    <TreeGridColumn Field="TaskName" HeaderText="Task Name" Width="140" ValidationRules="@(new ValidationRules() { Required = true })" ></TreeGridColumn>
                    <TreeGridColumn Field="StartDate" HeaderText="Start Date" Format="d" Width="100" TextAlign="TextAlign.Right" ></TreeGridColumn>
                    <TreeGridColumn Field="Duration" HeaderText="Duration" ValidationRules="@(new ValidationRules() { Number = true, Min = 0 })" Width="140" TextAlign="TextAlign.Right"></TreeGridColumn>
                    <TreeGridColumn Field="Progress" HeaderText="Progress" ValidationRules="@(new ValidationRules() {Required = true })" Width="100"></TreeGridColumn>
                    <TreeGridColumn Field="Priority" HeaderText="Priority" ValidationRules="@(new ValidationRules() {Required = true })" Width="100" ></TreeGridColumn>
                </TreeGridColumns>
            </SfTreeGrid>
        </div>
    </div>
</div>
@code {
    public List<DynamicDictionary> TreeData { get; set; }
    SfTreeGrid<DynamicDictionary> TreeGrid;
    protected override void OnInitialized()
    {
        this.TreeData = GetData().ToList();
    }
    public static List<DynamicDictionary> Data = new List<DynamicDictionary>();
    public static int ParentRecordID { get; set; }
    public static int ChildRecordID { get; set; }

    public static List<DynamicDictionary> GetData()
    {
        Data.Clear();
        ParentRecordID = 0;
        ChildRecordID = 0;
        for (var i = 1; i <= 60; i++)
        {
            Random ran = new Random();
            DateTime start = new DateTime(1992, 06, 07);
            int range = (DateTime.Today - start).Days;
            DateTime startingDate = start.AddDays(ran.Next(range));
            dynamic ParentRecord = new DynamicDictionary();
            ParentRecord.TaskID = ++ParentRecordID;
            ParentRecord.TaskName = "Parent Task " + i; ;
            ParentRecord.StartDate = startingDate;
            ParentRecord.Progress = ParentRecordID % 2 == 0 ? "In Progress" : "Open";
            ParentRecord.Priority = ParentRecordID % 2 == 0 ? "High" : "Low";
            ParentRecord.Duration = ParentRecordID % 2 == 0 ? 32 : 76;
            ParentRecord.ParentID = null;
            Data.Add(ParentRecord);
            AddChildRecords(ParentRecordID);
        }
        return Data;
    }
    public static void AddChildRecords(int ParentId)
    {
        for (var i = 1; i < 4; i++)
        {
            Random ran = new Random();
            DateTime start = new DateTime(1992, 06, 07);
            int range = (DateTime.Today - start).Days;
            DateTime startingDate = start.AddDays(ran.Next(range));
            dynamic ChildRecord = new DynamicDictionary();
            ChildRecord.TaskID = ++ParentRecordID;
            ChildRecord.TaskName = "Child Task " + ++ChildRecordID;
            ChildRecord.StartDate = startingDate;
            ChildRecord.Progress = ParentRecordID % 3 == 0 ? "Validated" : "Closed";
            ChildRecord.Priority = ParentRecordID % 3 == 0 ? "Low" : "Critical";
            ChildRecord.Duration = ParentRecordID % 3 == 0 ? 64 : 98;
            ChildRecord.ParentID = ParentId;
            Data.Add(ChildRecord);
        }
    }

    public class DynamicDictionary : DynamicObject
    {
        Dictionary<string, object> Dictionary = new Dictionary<string, object>();

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            string name = binder.Name;
            return Dictionary.TryGetValue(name, out result);
        }
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            Dictionary[binder.Name] = value;
            return true;
        }

        public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
        {
            return this.Dictionary?.Keys;
        }
    }
}
